
soundseg	segment public 'code'

main 	proc far

	assume cs:soundseg

	org 100h
start:

	jmp where_its_at

;-------------------------------------------------------------------------
;		strings
;-------------------------------------------------------------------------

instructions	db	13,10 dup (10),'Sounder by MicroHelp (404) 973-9272',13,10,10
	db	'Press ^C or Ctrl-Break to stop this program',13,10,10
	db	'Duration = How long to play the note before putting in a delay',13,10,10
	db	'Delay    = How long to pause between sounds',13,10,10
	db	'Magnitude= How fast to change the duration and the delay',13,10,10,10
	db      '  ',24,' = Higher tone                     ',25,' = Lower tone      ',13,10
        db      '--> = Longer duration               <-- = Shorter duration',13,10
	db	'  + = Longer delay between clicks     - = Shorter delay',13,10
	db	'  I = Increase magnitude of changes   D = Decrease magnitude'
	db	13,10,10
	db	'Tone: 00040  Duration: 10000  Delay: 10000  Magnitude: 01024$'
; for cursor posit     ^7               ^24           ^38               ^56

;-------------------------------------------------------------------------
;		values
;-------------------------------------------------------------------------

tone		db	40,0		;extra bytes/words for overflow
duration	dw	10000,0
delay		dw	10000,0
magnitude	dw	1024,0
divisor		dw	256,0

;-------------------------------------------------------------------------
;		procedures
;-------------------------------------------------------------------------

print_a_character	proc	near

	mov dl,'0'	

keep_trying:

	cmp ax,cx
	jb  too_far
	sub ax,cx		;down by whatever we're looking at
	inc dl
	jmp keep_trying

too_far:

	push ax			;save the value
	mov ah,2
	int 21h			;print the character
	pop ax			;restore it
	ret

print_a_character	endp
	
;-------------------------------------------------------------------------

print_zero	proc	near

	push ax			;save the value
	mov dl,'0'
	mov ah,2
	int 21h
	pop ax
	ret

print_zero	endp

;-------------------------------------------------------------------------

speaker	proc near

	mov al,182
	out 43h,al		; setup for sound
	mov al,0
	out 42h,al		; low part

	mov al,tone

	out 42h,al		; high part
	in al,61h
	push ax 		; save port value
	or al,3
	out 61h,al		; turn speaker on

	mov cx,duration

p125:	loop p125		; wait around
	pop ax			; restore original port value
	out 61h,al		; turn speaker off
	ret 

speaker	endp

;-------------------------------------------------------------------------

do_delay proc near

	mov cx,delay

delayloop:

	loop delayloop
	ret 

do_delay 	endp

;-------------------------------------------------------------------------

cursor 	proc	near

;dl has column

	dec dl			;subtract one for bios
	mov dh,24		;25th row
	xor bh,bh
	mov ah,2
	int 10h
	ret

cursor	endp

;-------------------------------------------------------------------------
;              End of procedures - this is main program
;-------------------------------------------------------------------------

where_its_at:

	mov dx,offset instructions	;print instructions
	mov ah,9
	int 21h


is_key_waiting:

	mov ah,0bh
	int 21h
	cmp al,0ffh		;has a key been pressed?
	jz  get_the_key
	jmp do_it        	;if not, go make some noise

get_the_key:

	mov ah,8		;go get the key
	int 21h			
	cmp al,0		;is it an extended key?
	jz extended_code	;if so, go to that area

	cmp al,73		;Is it an 'I'
	jz  increase_magnitude
	cmp al,105		;or an 'i'
	jz  increase_magnitude

	cmp al,68		;Is it a 'D'
	jz decrease_magnitude
	cmp al,100		;or a 'd'
	jz decrease_magnitude

	cmp al,43		;is it a plus sign?
	jz increase_delay
	
	cmp al,45		;or a minus sign
	jz decrease_delay

	jmp is_key_waiting	;then it wasn't a valid key

increase_magnitude:

	mov ax,magnitude	;double it
	cmp ax,32768		;if more than 32767, ignore
	jb do_inc
	jmp print_magnitude

do_inc:	
	shl ax,1
	mov magnitude,ax
	jmp print_magnitude

decrease_magnitude:

	mov ax,magnitude	;halve it
	cmp ax,1		;if one or less, ignore it
	ja do_dec
	jmp print_magnitude 

do_dec:

	shr ax,1
	mov magnitude,ax
	jmp print_magnitude

increase_delay:

	mov cx,magnitude
	add delay,cx
	jmp print_delay

decrease_delay:

	mov cx,magnitude
	sub delay,cx
	jmp print_delay
	

extended_code:

	mov ah,8		;go get second part of key
	int 21h
	cmp al,72		;is it an up arrow?
	jz  decrease_tone
	cmp al,80		;or maybe a down arrow
	jz  increase_tone
	cmp al,77		;is it a right arrow?
	jz  increase_duration
	cmp al,75		;how about a left arrow?
	jz  decrease_duration

	jmp is_key_waiting	;wrong key pressed

increase_tone:

	inc tone
	jmp check_tone
	
decrease_tone:

	dec tone

check_tone:

	cmp tone,1
	jb make_tone_127
	cmp tone,127
	ja make_tone_1
	jmp print_tone

make_tone_127:

	mov tone,127
	jmp print_tone

make_tone_1:

	mov tone,1
	jmp print_tone

increase_duration:

	mov cx,magnitude
	add duration,cx
	jmp print_duration

decrease_duration:

	mov cx,magnitude
	sub duration,cx
	jmp print_duration

print_tone:

	mov dl,7		;position the cursor at column 7
	call cursor
	mov al,tone		;set up the tone
	cbw			;make it a word
	jmp print_value

print_duration:

	mov dl,24
	call cursor
	mov ax,duration
	jmp print_value

print_delay:

	mov dl,38
	call cursor
	mov ax,delay
	jmp print_value

print_magnitude:

	mov dl,56
	call cursor
	mov ax,magnitude

print_value:

	cmp ax,9999		;is it more than 9,999?
	ja  tenthousand		;if so, go print it
	call print_zero         ;otherwise, print a zero
	jmp thousand

tenthousand:

	mov cx,10000
	call print_a_character
	
thousand:			;this just repeats what we did above

	cmp ax,999
	ja  do_thousand
	call print_zero
	jmp hundred

do_thousand:

	mov cx,1000
	call print_a_character

hundred:

	cmp ax,99
	ja  do_hundred
	call print_zero
	jmp ten

do_hundred:

	mov cx,100
	call print_a_character

ten:

	cmp ax,9
	ja  do_ten
	call print_zero
	jmp zero

do_ten:

	mov cx,10
	call print_a_character

zero:

	add ax,30h		;convert digit to ascii and print
	mov dl,al
	mov ah,2
	int 21h

do_it:

	call speaker		;make the noise
	call do_delay		;wait around for the delay
	jmp is_key_waiting

main		endp
soundseg	ends
end		start
 